package com.example.supplychainbackend.service.Impl;

import com.example.supplychainbackend.controller.dto.trace.CodeDto;
import com.example.supplychainbackend.controller.dto.trace.TimelineDto;
import com.example.supplychainbackend.controller.dto.trace.TraceInfoDto;
import com.example.supplychainbackend.dao.design.BOMDao;
import com.example.supplychainbackend.dao.plan.PlanOrderDao;
import com.example.supplychainbackend.dao.production.ProductionCertDao;
import com.example.supplychainbackend.dao.production.ProductionProcessDao;
import com.example.supplychainbackend.dao.production.ProductionSchedulingDao;
import com.example.supplychainbackend.dao.production.ProductionWorkorderDao;
import com.example.supplychainbackend.dao.project.ProjectDocsDao;
import com.example.supplychainbackend.dao.project.ProjectPlanDao;
import com.example.supplychainbackend.dao.quality.InspectionOrderDao;
import com.example.supplychainbackend.dao.quality.InspectionRequestDao;
import com.example.supplychainbackend.dao.sales.ContractDao;
import com.example.supplychainbackend.dao.sales.OrderDao;
import com.example.supplychainbackend.dao.warehouse.InboundBillDao;
import com.example.supplychainbackend.dao.warehouse.OutboundBillDao;
import com.example.supplychainbackend.entity.design.BOMEntity;
import com.example.supplychainbackend.entity.plan.MaterialInfoEntity;
import com.example.supplychainbackend.entity.plan.PlanOrderEntity;
import com.example.supplychainbackend.entity.production.ProductionCertEntity;
import com.example.supplychainbackend.entity.production.ProductionProcessEntity;
import com.example.supplychainbackend.entity.production.ProductionSchedulingEntity;
import com.example.supplychainbackend.entity.production.ProductionWorkorderEntity;
import com.example.supplychainbackend.entity.project.PlanDetailEntity;
import com.example.supplychainbackend.entity.project.ProjectPlanEntity;
import com.example.supplychainbackend.entity.quality.InspectionOrderEntity;
import com.example.supplychainbackend.entity.quality.InspectionRequestEntity;
import com.example.supplychainbackend.entity.sales.ContractEntity;
import com.example.supplychainbackend.entity.sales.OrderEntity;
import com.example.supplychainbackend.entity.warehouse.InboundBillEntity;
import com.example.supplychainbackend.entity.warehouse.OutboundBillEntity;
import com.example.supplychainbackend.service.TraceService;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class TraceServiceImpl implements TraceService {
    private final ProductionProcessDao productionProcessDao;
    private final OutboundBillDao outboundBillDao;
    private final ContractDao contractDao;
    private final OrderDao orderDao;
    private final PlanOrderDao planOrderDao;
    private final ProductionWorkorderDao productionWorkorderDao;
    private final ProductionSchedulingDao productionSchedulingDao;
    private final ProductionCertDao productionCertDao;
    private final InspectionOrderDao inspectionOrderDao;

    private final InspectionRequestDao inspectionRequestDao;
    private final InboundBillDao inboundBillDao;
    private final ProjectDocsDao projectDocsDao;
    private final ProjectPlanDao projectPlanDao;
    private final BOMDao bomDao;
    private final String sep = System.lineSeparator();

    public List<TimelineDto> assignIndex(List<TimelineDto> timeline){
        for (int i = 0; i < timeline.size(); i++) {
            TimelineDto item = timeline.get(i);
            item.setIndex(Integer.toString(i));
        }
        return timeline;
    }

    @Transactional
    public TraceInfoDto getTraceInfo(String batch) {
        List<TimelineDto> timeline = new ArrayList<>();
        Optional<ProductionProcessEntity> ppEntityOp = productionProcessDao.findByBatch(batch);
        ProductionProcessEntity productionProcessEntity = ProductionProcessEntity.builder().build();
        if (ppEntityOp.isEmpty())
            throw new RuntimeException("未查询到批次号备案");
        else {
            productionProcessEntity = ppEntityOp.get();
            if (2 != productionProcessEntity.getStatus())
                throw new RuntimeException("批次号备案审批未通过");
            String timeMessage =
                    "生产备案"+" 批次号："+batch
                            +" 产品："+productionProcessEntity.getProductName()
                            +" 企业："+productionProcessEntity.getEnterpriseName();
            if (productionProcessEntity.getOnChain()){
                timeMessage = timeMessage + sep+"链交易ID：" + productionProcessEntity.getTransactionId();
            }
            String addInfo = " 备案人："+productionProcessEntity.getUserName()
                    +" 电话："+productionProcessEntity.getPhone()
                    +" 备案生产时间："+productionProcessEntity.getTime();
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                            .addition(addInfo)
                    .build());
        }

        ProductionSchedulingEntity schedulingEntity = productionSchedulingDao.findByBatchNumber(batch);
        if (schedulingEntity == null){
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到生产批次")
                    .build());
            timeline = assignIndex(timeline);
            return  TraceInfoDto.builder()
                    .batch(batch)
                    .productName(productionProcessEntity.getProductName())
                    .certificate(productionProcessEntity.getCertificate())
                    //.productionOutPhoto()
                    //.salesInPhoto()
                    //.salesOutPhoto(obEntity.getOutPhoto())
                    .timeline(timeline)
                    .build();
        }else {
            String timeMessage =
                    "生产批次 "+batch
                            +" 企业："+schedulingEntity.getEnterpriseName()
                            +" 负责人："+schedulingEntity.getUserName()
                            +" 生产时间："+productionProcessEntity.getTime();
            if (schedulingEntity.getOnChain()){
                timeMessage = timeMessage + sep +"链交易ID：" + schedulingEntity.getTransactionId();
            }
            String addInfo = schedulingEntity.getArea() +" "
                    + schedulingEntity.getProductionLine() +" "
                    + schedulingEntity.getEquipmentName() + sep
                    + schedulingEntity.getMaterialCode() +" "+schedulingEntity.getMaterialName() + sep
                    + " 排产数量：" + schedulingEntity.getScheduledQuantity();
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                            .addition(addInfo)
                    .build());
        }

        Optional<InspectionOrderEntity> inspectionOrderEntityOp = inspectionOrderDao.findByReferenceDocumentNumber(batch);
        if (inspectionOrderEntityOp.isPresent()){
            InspectionOrderEntity dataEntity = inspectionOrderEntityOp.get();
            String timeMessage =
                    "检验单 "+dataEntity.getInspectionOrderNumber()
                            +" 检验员："+dataEntity.getInspector()
                            +" 质检方："+dataEntity.getEnterpriseName()
                            +" 检验时间："+dataEntity.getInspectionTime();
            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            Optional<InspectionRequestEntity> requestEntityOp = inspectionRequestDao.findById(dataEntity.getInspectionRequestNumber());
            String addInfo = "";
            if (requestEntityOp.isPresent())
                addInfo = addInfo + "送检方：" + requestEntityOp.get().getEnterpriseName() + sep;
            addInfo = addInfo +
                    "检验对象：" +dataEntity.getMaterialNumber() + " " + dataEntity.getMaterialName() + sep
                    +" 检验总量：" + dataEntity.getInspectionQuantity()
                    +" 执行标准："+dataEntity.getExecutionStandard();

            // 质检单放在批次后面
            timeline.add(1, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                            .addition(addInfo)
                    .build());
        }

        InboundBillEntity inboundBillEntity = inboundBillDao.findByBatchAndEnterpriseId(batch,
                productionProcessEntity.getEnterpriseId());
        String outPhotoUrl = null;
        String inboundStockId = null;
        if (inboundBillEntity == null) {
            timeline.add(TimelineDto.builder()
                    .message("未查询到生产入库单")
                    .build());
            timeline = assignIndex(timeline);
        }else{
            InboundBillEntity dataEntity = inboundBillEntity;
            inboundStockId = dataEntity.getStockId();
            String timeMessage =
                    "入库单 "+dataEntity.getId()
                            +" 仓库："+dataEntity.getWarehouse() + " " +dataEntity.getWarehouseLocation() + " "
                            +dataEntity.getWarehouseArea() + " "+dataEntity.getWarehousePosition()
                            +" 上游企业：" + dataEntity.getUpstream();
            String addInfo = " 入库时间："+dataEntity.getDatetime() + " 负责人："+dataEntity.getWorker()
                    +" 联系电话："+dataEntity.getPhone();
            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            timeline.add(TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(addInfo)
                    .build());
        }

        if (inboundBillEntity != null) {
            List<OutboundBillEntity> outboundBillEntities = outboundBillDao.findAllByStockId(inboundStockId);
            if (outboundBillEntities.isEmpty()){
                timeline.add(TimelineDto.builder()
                        .message("未查询到出库单")
                        .build());
            }else {
                String timeMessage = "";
                String addInfo = "";
                for (OutboundBillEntity dataEntity:
                        outboundBillEntities) {
                    if (outPhotoUrl == null)
                        outPhotoUrl = dataEntity.getOutPhoto();
                    timeMessage = timeMessage +
                            "出库单 "+dataEntity.getId()
                                    +" 仓库："+dataEntity.getWarehouse() +dataEntity.getWarehouseLocation()
                                    +" "+dataEntity.getWarehouseArea() +" "+dataEntity.getWarehousePosition()
                                    +" 下游企业："+ dataEntity.getDownstream();

                    addInfo = " 出库时间："+dataEntity.getDatetime() + " 负责人："+dataEntity.getWorker()
                            +" 联系电话："+dataEntity.getPhone();
                    if (dataEntity.getOnChain()){
                        timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
                    }
                }

                timeline.add(TimelineDto.builder()
                        .message(timeMessage)
                        .type("success")
                        .addition(addInfo)
                        .build());
            }
        }

        String ProductionWorkOrderNo = schedulingEntity.getWorkOrderNo();
        ProductionWorkorderEntity pwoEntity = productionWorkorderDao.findByWorkOrderNo(ProductionWorkOrderNo);
        if (pwoEntity == null){
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到生产工单")
                    .build());
            timeline = assignIndex(timeline);
            return  TraceInfoDto.builder()
                    .batch(batch)
                    .productName(productionProcessEntity.getProductName())
                    .certificate(productionProcessEntity.getCertificate())
                    //.productionOutPhoto()
                    //.salesInPhoto()
                    .salesOutPhoto(outPhotoUrl)
                    .timeline(timeline)
                    .build();
        }else {
            ProductionWorkorderEntity dataEntity = pwoEntity;
            String timeMessage =
                    "生产工单 "+dataEntity.getWorkOrderNo()
                            +" 企业："+dataEntity.getEnterpriseName()
                            +" 负责人：" + dataEntity.getUserName();
            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            String addInfo = dataEntity.getArea() +" "
                    + dataEntity.getProductionLine() +" "
                    + dataEntity.getProcessRoute() + sep
                    + "产品代码：" + dataEntity.getMaterialCode() +" " + sep
                    + "工单总量：" + dataEntity.getWorkOrderQuantity();
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(addInfo)
                    .build());
        }
        String planOrderNo = pwoEntity.getPlanOrderNo();
        PlanOrderEntity planOrderEntity = planOrderDao.findByWorkOrderNumber(planOrderNo);
        if(planOrderEntity == null){
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到计划工单")
                    .build());
            timeline = assignIndex(timeline);
            return  TraceInfoDto.builder()
                    .batch(batch)
                    .productName(productionProcessEntity.getProductName())
                    .certificate(productionProcessEntity.getCertificate())
                    //.productionOutPhoto()
                    //.salesInPhoto()
                    .salesOutPhoto(outPhotoUrl)
                    .timeline(timeline)
                    .build();
        }else {
            PlanOrderEntity dataEntity = planOrderEntity;
            String timeMessage =
                    "计划工单 "+dataEntity.getWorkOrderNumber()
                            +" 企业："+dataEntity.getEnterpriseName()
                            +" 负责人：" + dataEntity.getUserName() + sep;

            List<MaterialInfoEntity> materialInfoEntities = dataEntity.getMaterialItems();
            String bomAddition = "";
            for (MaterialInfoEntity matItem:
                materialInfoEntities) {
                String matCode = matItem.getMaterialCode();
                int dashIndex = matCode.lastIndexOf("-");

                String inboundBatch = "";
                String inboundUpstream = "";
                if (dashIndex != -1) {
                    String stockId = matCode.substring(dashIndex + 1);
                    InboundBillEntity inboundBill = inboundBillDao.findByStockId(stockId);
                    if (inboundBill!=null){
                        inboundBatch = inboundBill.getBatch();
                        inboundUpstream = inboundBill.getUpstream();
                    }

                }

                bomAddition = bomAddition +
                        matItem.getMaterialCode() +" " +matItem.getMaterialName()+" "
                        +" " + inboundUpstream +" 批次号：" + inboundBatch + sep;
//
//                timeMessage = timeMessage +
//                        "{"+matItem.getMaterialCode() +" " +matItem.getMaterialName()+" "
//                        +inboundBatch +" " + inboundUpstream + "}"+ sep;
//                bomAddition = bomAddition +
//                        matItem +" "
//                        +inboundBatch +" " + inboundUpstream + sep;
            }

            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(bomAddition)
                    .build());
        }

        String salesOrderNo = planOrderEntity.getSalesOrderNo();
        Optional<OrderEntity> salesOrderEntityOp = orderDao.findById(salesOrderNo);
        if (salesOrderEntityOp.isEmpty()) {
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到销售订单")
                    .build());
            timeline = assignIndex(timeline);
            return  TraceInfoDto.builder()
                    .batch(batch)
                    .productName(productionProcessEntity.getProductName())
                    .certificate(productionProcessEntity.getCertificate())
                    //.productionOutPhoto()
                    //.salesInPhoto()
                    .salesOutPhoto(outPhotoUrl)
                    .timeline(timeline)
                    .build();
        }else {
            OrderEntity dataEntity = salesOrderEntityOp.get();
            String timeMessage =
                    "销售订单 "+dataEntity.getId()
                            +" 承接方："+dataEntity.getEnterpriseName()
                            +" 创建日期："+dataEntity.getOrderDate();
            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            String addInfo = "合同编号：" + dataEntity.getContractNumber();
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(addInfo)
                    .build());
        }

//        List<ProjectPlanEntity> projectPlans = projectPlanDao.findAllBySalesOrderNo(salesOrderNo);
//        if (projectPlans.isEmpty()) {
//            timeline.add(1, TimelineDto.builder()
//                    .message("未查询到项目计划")
//                    .build());
//            timeline = assignIndex(timeline);
//        }else {
//            String timeMessage = "";
//            for (ProjectPlanEntity plan:
//                 projectPlans) {
//                timeMessage = timeMessage +
//                        "项目计划 " + plan.getProjectPlanNo()+sep ;
//                List<PlanDetailEntity> items = plan.getPlanDetail();
//                for (PlanDetailEntity detail:
//                     items) {
//                    timeMessage = timeMessage + " - "
//                            +detail.getProcessNode()
//                            + " " + detail.getPlannedStartDate() + " " + detail.getPlannedEndDate()
//                            +sep;
//                }
//                if (plan.getOnChain()){
//                    timeMessage = timeMessage + "链交易ID：" + plan.getTransactionId();
//                }
//            }
//
//            timeline.add(1, TimelineDto.builder()
//                    .message(timeMessage)
//                    .type("success")
//                    .build());
//        }

        List<BOMEntity> bomEntities = bomDao.findAllByOrderId(salesOrderNo);
        if (bomEntities.isEmpty()) {
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到产品设计")
                    .build());
        }else {
            String timeMessage = "产品设计 "+salesOrderNo+sep;
            String designBom = "";
            for (BOMEntity bom:
                    bomEntities) {
//                timeMessage = timeMessage +
//                        "{" + bom.getMaterialCode() +" " +bom.getMaterialName()+"} "
//                         + sep;
//                designBom = designBom + bom + sep;
                designBom = designBom +
                        bom.getMaterialCode() +" " +bom.getMaterialName()+ " " + bom.getMaterialDesc()
                         + sep;
            }
            timeline.add(1, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(designBom)
                    .build());
        }

        OrderEntity salesOrderEntity = salesOrderEntityOp.get();
        String contractNumber = salesOrderEntity.getContractNumber();

        Optional<ContractEntity> contractEntityOp = contractDao.findById(contractNumber);
        if (contractEntityOp.isEmpty()){
            timeline.add(0, TimelineDto.builder()
                    .message("未查询到销售合同")
                    .build());
            timeline = assignIndex(timeline);
            return  TraceInfoDto.builder()
                    .batch(batch)
                    .productName(productionProcessEntity.getProductName())
                    .certificate(productionProcessEntity.getCertificate())
                    //.productionOutPhoto()
                    //.salesInPhoto()
                    .salesOutPhoto(outPhotoUrl)
                    .timeline(timeline)
                    .build();
        } else {
            ContractEntity dataEntity = contractEntityOp.get();
            String timeMessage =
                    "销售合同 "+dataEntity.getContractNumber()
                            +" 签订方："+dataEntity.getEnterpriseName()
                            +" 签订日期："+dataEntity.getSignDate();
            if (dataEntity.getOnChain()){
                timeMessage = timeMessage +sep +"链交易ID：" + dataEntity.getTransactionId();
            }
            String addInfo = "客户：" + dataEntity.getCustomerName();
            timeline.add(0, TimelineDto.builder()
                    .message(timeMessage)
                    .type("success")
                    .addition(addInfo)
                    .build());
        }
        timeline = assignIndex(timeline);
        List<ProductionCertEntity> prdCerts = productionCertDao.findAllByEnterpriseId(productionProcessEntity.getEnterpriseId());
        List<String> prdCertUrls = new ArrayList<>();
        for (ProductionCertEntity cert:
            prdCerts) {
            prdCertUrls.add(cert.getFileImg());
        }

        TraceInfoDto result = TraceInfoDto.builder()
                .batch(batch)
                .company(productionProcessEntity.getEnterpriseName())
                .productName(productionProcessEntity.getProductName())
                .certificate(productionProcessEntity.getCertificate())
                .productionOutPhoto(outPhotoUrl)
                .technology(prdCertUrls)
                //.salesInPhoto()
//                .salesOutPhoto(outPhotoUrl)
                .timeline(timeline)
                .build();

        return result;
    }


//    @Override
//    public CodeDto getCodeByBatch(CodeRequestDto request) {
    @Override
    public CodeDto getCodeByBatch(String bn) {
        ProductionSchedulingEntity schedulingEntity = productionSchedulingDao.findByBatchNumber(bn);
        if (schedulingEntity == null){
            throw new RuntimeException("不存在该批次号");
        }
        Optional<ProductionProcessEntity> processEntityOp = productionProcessDao.findByBatch(bn);
        if (processEntityOp.isEmpty()){
            throw new RuntimeException("该批次未备案");
        }
        ProductionProcessEntity processEntity = processEntityOp.get();
        if (processEntity.getStatus() != 2){
            throw new RuntimeException("该批次溯源码申请未通过");
        }
        CodeDto res = CodeDto.builder().batch(bn)
                .company(schedulingEntity.getEnterpriseName())
                .productName(processEntity.getProductName())
//                .productName(request.getProductName())
                .qrCodeUrl("localhost:8080/api/trace/traceInfo/"+bn).build();
        return res;
    }
}
